package com.ruoyi.kanaimqtt.controller;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.crc.CrcUtils;
import com.ruoyi.common.utils.MqttLockUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.kanaimqtt.Service.MqttGateway;
import com.ruoyi.kanaimqtt.common.BoxWaringUtil;
import com.ruoyi.kanaimqtt.common.probuf.Devicebuf;
import com.ruoyi.system.domain.app.Device;
import com.ruoyi.system.domain.app.PowerBilling;
import com.ruoyi.system.domain.app.RechargeOrder;
import com.ruoyi.system.mapper.PowerBillingMapper;
import com.ruoyi.system.mapper.app.DeviceMapper;
import com.ruoyi.system.mapper.app.RechargeOrderMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Slf4j
@RestController
public class OpenController {

    @Autowired
    MqttGateway mqttGateway;
    @Autowired
    DeviceMapper deviceMapper;
    @Autowired
    RechargeOrderMapper rechargeOrderMapper;
    @Autowired
    PowerBillingMapper powerBillingMapper;
    @Value("${sendTopic}")
    String sendTopic;
    @Autowired
    MqttLockUtil mqttLockUtil;
    @Autowired
    BoxWaringUtil boxWaringUtil;



    @PostMapping("/device/status")
    public void deviceStatus(@RequestHeader String token, @RequestBody JSONObject jsonObject){
        if ("nbiot".equals(token)) {
            log.info("接收消息:{}", jsonObject.toJSONString());
            Device device = deviceMapper.selectByNum(jsonObject.getString("clientid"));
            if (StringUtils.isNull(device)) {
                return;
            }
            if (jsonObject.getString("event").contains("disconnected")) {
                device.setDeviceLineState(0);
                device.setOffLineTime(new Date());
                log.info("设备：{},下线", jsonObject.getString("clientid"));
                boxWaringUtil.addEvent(jsonObject.getString("clientid"),null,1,2,"设备下线");
            } else if (jsonObject.getString("event").contains("connected")) {
                device.setDeviceLineState(1);
                device.setLineTime(new Date());
                log.info("设备：{},上线", jsonObject.getString("clientid"));
                boxWaringUtil.addEvent(jsonObject.getString("clientid"),null,1,1,"设备上线");
            }
            deviceMapper.updateByPrimaryKeySelective(device);
        }
    }

    @PostMapping("/set-config")
    public AjaxResult setConfig(@RequestBody Device device){
        List<PowerBilling> powerBillings=new ArrayList<>();
        for(int i=0;i<5;i++){
            PowerBilling billing = new PowerBilling();
            billing.setMaxPower(0D);
            billing.setMoney(new BigDecimal(0));
            powerBillings.add(billing);
        }
       for(int i=0;i<device.getPowerBillings().size();i++) {
           powerBillings.set(i,device.getPowerBillings().get(i));
       }

        StringBuilder hex = new StringBuilder();

        hex.append(String.format("%02x",32));
        hex.append(String.format("%08x",1));
        hex.append(String.format("%02x",device.getBillingType()==null ? 0 :device.getBillingType()));
        hex.append(String.format("%04x",device.getElectricityMoney()==null? 0 :device.getElectricityMoney().intValue()*100));
        hex.append(String.format("%04x",device.getTimeBilling()==null? 0:device.getTimeBilling().intValue()*100));
        if(device.getPowerBillings().size()==0){
            hex.append(String.format("%02x",0));
            hex.append(String.format("%04x",0));
            hex.append(String.format("%02x",0));
            hex.append(String.format("%04x",0));
            hex.append(String.format("%02x",0));
            hex.append(String.format("%04x",0));
            hex.append(String.format("%02x",0));
            hex.append(String.format("%04x",0));
            hex.append(String.format("%02x",0));
            hex.append(String.format("%04x",0));
        }else {
            powerBillings.forEach(s->{
                hex.append(String.format("%02x",s.getMaxPower().intValue()/10));
                hex.append(String.format("%04x",s.getMoney().intValue()*100));

            });
        }
        hex.append(String.format("%02x",device.getMaxPower()==null? 0 :device.getMaxPower().intValue()/10));
        hex.append(String.format("%02x",device.getCollectionTime()==null? 0 :device.getCollectionTime()));
        hex.append(String.format("%02x",device.getPeriodTime()==null? 0 :device.getPeriodTime()));
        hex.append(String.format("%02x",device.getMinPower()==null? 0 :device.getMinPower().intValue()/10));
        hex.append(String.format("%02x",device.getContinuePower()==null? 0 :device.getContinuePower()/10));
        hex.append(String.format("%02x",device.getContinueTime()==null? 0 :device.getEndTime()));
        String crc3 = CrcUtils.getCRC3(hexString2Bytes(hex.toString()));
        hex.append(reverse(crc3));

        deviceMapper.updateByPrimaryKeySelective(device);

        mqttGateway.sendToMqttBytes(hexString2Bytes(hex.toString()),sendTopic+device.getDeviceNum()+"/set");

        return AjaxResult.success();
    }

    //下发开始充电
    @GetMapping("/start/charge")
    public AjaxResult startCharge(@RequestParam Integer orderTime,
                                  @RequestParam String deviceNum,@RequestParam Integer socketNo,@RequestParam BigDecimal userBalance) {

        StringBuilder hex = new StringBuilder();
        hex.append(String.format("%02x",18));
        hex.append(String.format("%08x",1));
        hex.append(String.format("%08x",0));
        hex.append(String.format("%02x",socketNo));
        hex.append(String.format("%08x",userBalance.multiply(new BigDecimal("100")).intValue()));
        hex.append(String.format("%02x",orderTime==0 ? 0:1));
        hex.append(String.format("%04x",orderTime*60));
        String crc3 = CrcUtils.getCRC3(hexString2Bytes(hex.toString()));
        hex.append(reverse(crc3));

        System.out.println(Arrays.toString(hexString2Bytes(hex.toString())));
         mqttGateway.sendToMqttBytes(hexString2Bytes(hex.toString()),sendTopic+deviceNum+"/orderCreat");
        return AjaxResult.success();
    }


    //下发临时充电充电
    @GetMapping("/start/pay/charge")
    public AjaxResult startPayCharge(@RequestParam BigDecimal orderMoney,
                                     @RequestParam Integer socketNo,@RequestParam String deviceNum)  {
        StringBuilder hex = new StringBuilder();
        hex.append(String.format("%02x",18));
        hex.append(String.format("%08x",1));
        hex.append(String.format("%08x",0));
        hex.append(String.format("%02x",socketNo));
        hex.append(String.format("%08x",orderMoney.multiply(new BigDecimal("100")).intValue()));
        hex.append(String.format("%02x",2));
        hex.append(String.format("%04x",orderMoney.multiply(new BigDecimal("100")).intValue()));
        String crc3 = CrcUtils.getCRC3(hexString2Bytes(hex.toString()));
        hex.append(reverse(crc3));
        hexString2Bytes(hex.toString());
        System.out.println(Arrays.toString(hexString2Bytes(hex.toString())));
        mqttGateway.sendToMqttBytes(hexString2Bytes(hex.toString()),sendTopic+deviceNum+"/orderCreat");
        return AjaxResult.success();
    }

    //下发结束充电
    @GetMapping("/end/charge")
    public AjaxResult endCharge(@RequestParam String deviceNum,@RequestParam Integer socketNo){

        StringBuilder hex = new StringBuilder();
        hex.append(String.format("%02x",8));
        hex.append(String.format("%08x",1));
        hex.append(String.format("%02x",socketNo));
        hex.append(String.format("%02x",0));

        String crc3 = CrcUtils.getCRC3(hexString2Bytes(hex.toString()));
        hex.append(reverse(crc3));

        mqttGateway.sendToMqttBytes(hexString2Bytes(hex.toString()),sendTopic+deviceNum+"/orderStop");
        return AjaxResult.success();
    }



    //重启
    @GetMapping("/restart")
    public AjaxResult restartDevice(@RequestParam String deviceNum){
        Devicebuf.restart.Builder builder = Devicebuf.restart.newBuilder();
        builder.setTs(System.currentTimeMillis()/1000);

        mqttGateway.sendToMqttBytes(builder.build().toByteArray(), sendTopic+deviceNum+"/chargingTest");
        return AjaxResult.success();
    }

    //握手
    @GetMapping("/check")
    public AjaxResult check(@RequestParam String deviceNum,@RequestParam String msgId){
        Devicebuf.checkStatus.Builder checkStatus = Devicebuf.checkStatus.newBuilder();
        checkStatus.setMsgId(Integer.parseInt(msgId));

        mqttGateway.sendToMqttBytes(checkStatus.build().toByteArray(),sendTopic +deviceNum+"/checkStatus");
        log.info("握手成功::"+msgId);
        return AjaxResult.success();
    }

    //把16进制字符串转换成字节数组
    public static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    public static byte[] hexString2Bytes(String hex) {

        if ((hex == null) || (hex.equals(""))) {
            return null;
        } else if (hex.length() % 2 != 0) {
            return null;
        } else {
            hex = hex.toUpperCase();
            int len = hex.length() / 2;
            byte[] b = new byte[len];
            char[] hc = hex.toCharArray();
            for (int i = 0; i < len; i++) {
                int p = 2 * i;
                b[i] = (byte) (charToByte(hc[p]) << 4 | charToByte(hc[p + 1]));
            }
            return b;
        }
    }

    public static String reverse(String crc3){
        crc3=crc3.substring(crc3.length()-4);
        String end =crc3.substring(0,2);
        String result=crc3.substring(crc3.length()-2)+end;
        return result.toLowerCase();
    }
}
